package gnss

import (
	"fmt"
	"math"
)

/**
  轨道改正
  msgid: 1057(GPS), 1063(GLO)
*/

type IgmasSsrOrbCorrectionSat struct {
	Satid       uint8
	Iode        uint8
	BdsIode     uint16
	BdsIodecr   uint32
	DRadial     float64
	DAlongTrack float64
	DCrossTrack float64

	DotDRadial     float64
	DotDAlongTrack float64
	DotDCrossTrack float64
}

func (this *IgmasSsrOrbCorrectionSat) String() string {
	return fmt.Sprintf("SatId:%d, Iode:%d, DRadial:%.4f, DAlongTrack:%.4f, DCrossTrack:%.4f, DotDRadial:%.6f, DotDAlongTrack:%.6f, DotDCrossTrack:%.6f",
		this.Satid, this.Iode, this.DRadial, this.DAlongTrack, this.DCrossTrack, this.DotDRadial, this.DotDAlongTrack, this.DotDCrossTrack)
}

func EncodeIgmasSsrOrbCorrection(head *IgmasSsrCorrectionHead, lst []*IgmasSsrOrbCorrectionSat, outBuf []byte, startBitN int) (bitN int) {
	bitN = EncodeIgmasSsrHead(head, outBuf, startBitN, len(lst))

	for i := 0; i < len(lst); i++ {
		itm := lst[i]
		SetBitU8(outBuf, bitN, 6, itm.Satid)
		bitN += 6

		if head.MsgId == 1258 {
			SetBitU16(outBuf, bitN, 10, itm.BdsIode)
			bitN += 10
			SetBitU16(outBuf, bitN, 24, itm.BdsIode)
			bitN += 24
		} else {
			SetBitU8(outBuf, bitN, 8, itm.Iode)
			bitN += 8
		}

		SetBitI32(outBuf, bitN, 22, int32(math.Round(itm.DRadial/1e-4)))
		bitN += 22

		SetBitI32(outBuf, bitN, 20, int32(math.Round(itm.DAlongTrack/4e-4)))
		bitN += 20

		SetBitI32(outBuf, bitN, 20, int32(math.Round(itm.DCrossTrack/4e-4)))
		bitN += 20

		SetBitI32(outBuf, bitN, 21, int32(math.Round(itm.DotDRadial/1e-6)))
		bitN += 21

		SetBitI32(outBuf, bitN, 19, int32(math.Round(itm.DotDAlongTrack/4e-6)))
		bitN += 19

		SetBitI32(outBuf, bitN, 19, int32(math.Round(itm.DotDCrossTrack/4e-6)))
		bitN += 19
	}

	return
}

func DecodeIgmasSsrOrbCorrection(inBuf []byte, startBitN int) (head *IgmasSsrCorrectionHead, lst []*IgmasSsrOrbCorrectionSat, bitN int) {
	bitN = startBitN
	head = &IgmasSsrCorrectionHead{}
	head.MsgId = GetBitU16(inBuf, bitN, 12)
	bitN += 12

	if head.MsgId == 1063 {
		head.Tow = GetBitU32(inBuf, bitN, 17)
		bitN += 17
	} else {
		head.Tow = GetBitU32(inBuf, bitN, 20)
		bitN += 20
	}

	head.UpIntv = GetBitU8(inBuf, bitN, 4)
	bitN += 4

	head.SyncFlag = GetBitU8(inBuf, bitN, 1)
	bitN += 1

	head.Refd = GetBitU8(inBuf, bitN, 1)
	bitN += 1

	head.IOD = GetBitU8(inBuf, bitN, 4)
	bitN += 4

	head.ProvID = GetBitU16(inBuf, bitN, 16)
	bitN += 16

	head.SolID = GetBitU8(inBuf, bitN, 4)
	bitN += 4

	n := GetBitU8(inBuf, bitN, 6)
	bitN += 6
	lst = make([]*IgmasSsrOrbCorrectionSat, n)
	for i := 0; i < len(lst); i++ {
		itm := &IgmasSsrOrbCorrectionSat{}
		lst[i] = itm
		itm.Satid = GetBitU8(inBuf, bitN, 6)
		bitN += 6

		if head.MsgId == 1258 {
			itm.BdsIode = GetBitU16(inBuf, bitN, 10)
			bitN += 10

			itm.BdsIodecr = GetBitU32(inBuf, bitN, 24)
			bitN += 24
		} else {
			itm.Iode = GetBitU8(inBuf, bitN, 8)
			bitN += 8

		}

		itm.DRadial = float64(GetBitI32(inBuf, bitN, 22)) * 1e-4
		bitN += 22

		itm.DAlongTrack = float64(GetBitI32(inBuf, bitN, 20)) * 4e-4
		bitN += 20

		itm.DCrossTrack = float64(GetBitI32(inBuf, bitN, 20)) * 4e-4
		bitN += 20

		itm.DotDRadial = float64(GetBitI32(inBuf, bitN, 21)) * 1e-6
		bitN += 21

		itm.DotDAlongTrack = float64(GetBitI32(inBuf, bitN, 19)) * 4e-6
		bitN += 19

		itm.DotDCrossTrack = float64(GetBitI32(inBuf, bitN, 19)) * 4e-6
		bitN += 19
	}

	return
}
